package com.example.dps;



import com.google.gson.JsonObject;
import com.loopj.android.http.*;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;

/**
 * 
 * @author merrickc
 * 
 * contains useful functions for sending info and querying the web server. (ie Logins, registration)
 *
 */
public class WebHelper {
	
	
	Object mLock = new Object();
	
	Context activity;
	
	String tag = "WebServer";
	
	//public static final String DOMAIN = "10.1.10.107";
	
	public static final String DOMAIN = "downpaymentsaver.com";
	
	static String DPSSERVER = "https://" + DOMAIN + "/downpaymentserver/";
	
	
	DBHelper dbHelper;
	
	AccountDBHelper accountDBHelper;
	
	
	//public static AsyncHttpClient client = new AsyncHttpClient();
	
	public HttpContext httpContext;
	public static PersistentCookieStore cookieStore;
	

	ProgressDialog progressDialog;
	
	List<Cookie> cookies = null;
	
	
	/**
	 * should the user stay logged in?
	 * value passed by webHelper.login function
	 */
	boolean rememberUser = false;
	
	
	public WebHelper(Context context){
		
		this.activity = context;
		
		this.dbHelper = new DBHelper(context);
		
		this.accountDBHelper = new AccountDBHelper(context);
		
		cookieStore = new PersistentCookieStore(this.activity);
		//client.setCookieStore(cookieStore);
		
		
		        
	}
	
	
	public class getTransfersTask extends AsyncTask<Void, Integer, Boolean>{

		@Override
		protected Boolean doInBackground(Void... params) {
			
			HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "getTransfers.php");
	        
	        
	        // Create local HTTP context
		    httpContext = new BasicHttpContext();
		    // Bind custom cookie store to the local context
		    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		    

	        // Execute HTTP Post Request
	        try {
				HttpResponse response = httpclient.execute(httppost, httpContext);
				String result = EntityUtils.toString(response.getEntity());
				Log.e(tag, "G Transfer RESPONSE");
				Log.e("WEB RESPONSE", result);
				
				JSONObject jsonObject = null;
				
				try {
					jsonObject = new JSONObject(result);
					result = jsonObject.getString("status");
					Log.e(tag, result);
					
					if(result.equals("success")) return true;
					
					
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			return false;
		}
		
		
	}
	
	public class performTransferTask extends AsyncTask<Integer, Integer, Boolean>{

		@Override
		protected Boolean doInBackground(Integer... params) {
			
			int fromAccountID = params[0];
			int toAccountID = params[1];
			int amount = params[2];
			
			JSONObject json = new JSONObject();
			
			
			try {
				
				json.put("fromAccountID", fromAccountID);
				json.put("toAccountID", toAccountID);
				json.put("amount", amount);
				
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "performTransfer.php");
		    
		    List<NameValuePair> values = new ArrayList<NameValuePair>();
	        values.add(new BasicNameValuePair("json", json.toString()));
	        
	        
	        // Create local HTTP context
		    httpContext = new BasicHttpContext();
		    // Bind custom cookie store to the local context
		    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		    
	        try {
				httppost.setEntity(new UrlEncodedFormEntity(values));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

	        // Execute HTTP Post Request
	        try {
				HttpResponse response = httpclient.execute(httppost, httpContext);
				String result = EntityUtils.toString(response.getEntity());
				Log.e(tag, "Perform Transfer RESPONSE");
				Log.e("WEB RESPONSE", result);
				
				JSONObject jsonObject = null;
				
				try {
					jsonObject = new JSONObject(result);
					result = jsonObject.getString("status");
					Log.e(tag, result);
					
					if(result.equals("success")) return true;
					
					
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			return false;
		}

		
	}
	
	
	public class checkSessionTask extends AsyncTask<String, Integer, Boolean>{

		@Override
		protected Boolean doInBackground(String... usernames) {
			
			String username = usernames[0];
			
			// TODO Auto-generated method stub
			Log.e(tag, "Checking Session for : " + username);
			
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
	        nameValuePairs.add(new BasicNameValuePair("username", username));
	        
			HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "/checkSession.php");
		    
		    try {
				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		    
		    
		    boolean sessionOpen = false;
		    
		    // Create local HTTP context
		    httpContext = new BasicHttpContext();
		    // Bind custom cookie store to the local context
		    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		    


	        try {
	        	
	        	Log.e(tag, "EXECUTING HTTPPOST");
				HttpResponse response = httpclient.execute(httppost, httpContext);
				
				//saveCookies();
				
				String result = EntityUtils.toString(response.getEntity());
				Log.e("WEB RESPONSE", "*** (in check Session Task) result = " +result);

				JSONObject jsonObject = null;
				
				try {
					jsonObject = new JSONObject(result);
					
					result = jsonObject.getString("status");
					
					if(result.equals("success")){
						sessionOpen = true;
						return sessionOpen;
					}
					else{
						sessionOpen = false;
						return sessionOpen;
					}
					
				} catch (JSONException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				

				
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

	       return sessionOpen;
				
		}
		
		
	}
	
	
	/** sends updated user info to the server **/
	public class updateUserInfoTask extends AsyncTask<JSONObject, Integer, Boolean>{

		@Override
		protected Boolean doInBackground(JSONObject... objects) {
			
			JSONObject json = objects[0];

			HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "updateUser.php");
		    
		    List<NameValuePair> values = new ArrayList<NameValuePair>();
	        values.add(new BasicNameValuePair("json", json.toString()));
		    
		    // Create local HTTP context
		    httpContext = new BasicHttpContext();
		    // Bind custom cookie store to the local context
		    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		    
	        try {
				httppost.setEntity(new UrlEncodedFormEntity(values));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

	        // Execute HTTP Post Request
	        try {
				HttpResponse response = httpclient.execute(httppost, httpContext);
				String result = EntityUtils.toString(response.getEntity());
				Log.e(tag, "UPDATE USER RESPONSE");
				Log.e("WEB RESPONSE", result);
				
				JSONObject jsonObject = null;
				
				try {
					jsonObject = new JSONObject(result);
					result = jsonObject.getString("status");
					Log.e(tag, result);
					
					if(result.equals("success")) return true;
					
					
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			return false;
		}
		
		
		
	}
	
	/** sends updated account info to the server **/
	public class updateAccountInfoTask extends AsyncTask<JSONObject, Integer, Boolean>{
		
		ProgressDialog dialog;
			
		Context context;
		
		updateAccountInfoTask(Context context){
			
			this.context = context;
			dialog = new ProgressDialog(context);
		}
		
		
		
		@Override
        protected void onPreExecute() {
			super.onPreExecute();

			
			dialog = ProgressDialog.show(WebHelper.this.activity,
	                "", "Updating Account Information");
			
		}
			
			

		@Override
		protected Boolean doInBackground(JSONObject... objects) {
			
			JSONObject json = objects[0];

			HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "updateAccounts.php");
		    
		    List<NameValuePair> values = new ArrayList<NameValuePair>();
	        values.add(new BasicNameValuePair("json", json.toString()));
		    
		    // Create local HTTP context
		    httpContext = new BasicHttpContext();
		    // Bind custom cookie store to the local context
		    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		    
	        try {
				httppost.setEntity(new UrlEncodedFormEntity(values));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

	        // Execute HTTP Post Request
	        try {
				HttpResponse response = httpclient.execute(httppost, httpContext);
				String result = EntityUtils.toString(response.getEntity());
				//Log.e(tag, "UPDATE ACCOUNT RESPONSE");
				Log.e("WEB RESPONSE", result);
				
				JSONObject jsonObject = null;
				
				try {
					jsonObject = new JSONObject(result);
					result = jsonObject.getString("status");
					Log.e(tag, result);
					
					if(result.equals("success")) return true;
					
					
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			return false;
		}
		
		@Override
		public void onPostExecute(Boolean result){
			
			super.onPostExecute(result);
			
			//dialog.dismiss();
			if(!result){
				Toast.makeText(this.context, "Failed to log in", Toast.LENGTH_LONG).show();
			}

	        if (dialog.isShowing()) {
	            dialog.dismiss();
	        }
			
		}
		
		
	}

	public class getAccountInfoTask extends AsyncTask<Integer, String, Boolean>{

		DBHelper dbHelper;
		
		AccountDBHelper accountDBHelper;
		
		ProgressDialog dialog;
		
		Context context;
		
		getAccountInfoTask(Context context){
			
			this.context = context;
			dialog = new ProgressDialog(context);
			
			this.accountDBHelper = new AccountDBHelper(context);
			this.dbHelper = new DBHelper(context);
		}
		
		
		
		@Override
        protected void onPreExecute() {
			super.onPreExecute();

			
			dialog = ProgressDialog.show(context,
	                "", "Retrieving Account Information");
			
		}
		@Override
		protected Boolean doInBackground(Integer... userids) {
			
			String userid = String.valueOf(userids[0]);
			

			HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "getAccounts.php");
		    
//		    List<NameValuePair> values = new ArrayList<NameValuePair>();
//	        values.add(new BasicNameValuePair("userid", userid));
		    
		    // Create local HTTP context
		    httpContext = new BasicHttpContext();
		    // Bind custom cookie store to the local context
		    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		    
//	        try {
//				httppost.setEntity(new UrlEncodedFormEntity(values));
//			} catch (UnsupportedEncodingException e) {
//				e.printStackTrace();
//			}

	        // Execute HTTP Post Request
	        try {
				HttpResponse response = httpclient.execute(httppost, httpContext);
				String result = EntityUtils.toString(response.getEntity());
				Log.e(tag, "getAccountInfo RESPONSE");
				Log.e("WEB RESPONSE", result);
				try {
					
					String[] objects = result.split("!!");
					
					/** make sure the account table is empty **/
					this.accountDBHelper.deleteAll();
					
					for(String entry : objects){
						Log.e("jsonEntry", entry + " : ");
						JSONObject jsonObject = new JSONObject(entry);
						
						
						Log.e(tag, entry);	
						Log.e(tag, "***********");
						
						//add parsed account to account DBHelper
						
						if(jsonObject.has("status") && jsonObject.getString("status").equals("fail")){
							
							return false;
						}
						
						Account account = new Account(jsonObject);
						this.accountDBHelper.addAccount(account);
						
						
						
						
					}
					
					
					return true;
						
					
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			return false;

		}
		
//		@Override
//		public void onProgressUpdate(String... response){
//			String status = response[0];
//			String message = response[1];
//			if(status.equals("fail")){
//				Toast.makeText(WebHelper.this.activity,message, Toast.LENGTH_LONG).show();
//				
//				if(message.equals("You must be logged in")){
//					
//					WebHelper.this.logout();
//					
//					Intent intent = new Intent(WebHelper.this.activity, LoginActivity.class);
//					WebHelper.this.authenticate("view_savings");
//					
//				}
//				
//				
//			}
//			
//		}
		
		@Override
		public void onPostExecute(Boolean result){
			
			super.onPostExecute(result);
			
			if(activity instanceof ViewSavingsActivity){
				((ViewSavingsActivity) activity).onGetAccountInfo(result);
			}
			
			if(activity instanceof AddMoneyActivity){
				((AddMoneyActivity) activity).onGetAccountInfo(result);
			}
			

			try{
		        if (dialog.isShowing()) {
		            dialog.dismiss();
		        }
			}
			catch(Exception e){
				//nothing to do here;
			}

			
		}
		
		
		
	}
	
	public class createAccountTask extends AsyncTask<JSONObject, Integer, Boolean>{

		@Override
		protected Boolean doInBackground(JSONObject... objects) {
			
			JSONObject object = objects[0];
			HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "/createAccount.php");
		    
		    List<NameValuePair> jsonValues = new ArrayList<NameValuePair>();
	        jsonValues.add(new BasicNameValuePair("json", object.toString()));
		    
		    // Create local HTTP context
		    httpContext = new BasicHttpContext();
		    // Bind custom cookie store to the local context
		    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		    
	        try {
				httppost.setEntity(new UrlEncodedFormEntity(jsonValues));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

	        // Execute HTTP Post Request
	        try {
				HttpResponse response = httpclient.execute(httppost, httpContext);
				String result = EntityUtils.toString(response.getEntity());
				Log.e(tag, "CREATE ACCOUNT RESPONSE");
				Log.e("WEB RESPONSE", result);
				try {
					JSONObject jsonObject = new JSONObject(result);
					
					if(jsonObject.getString("status").equals("success")){
						Log.e(tag, "CREATE ACCOUNT SUCCESS");
						return true;
						
					}
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			return false;

		}
		
		@Override
		protected void onPostExecute(Boolean result){
			
			Log.e(tag, "FINISHED CREATE ACCOUNT TASK");
			if(result == true) WebHelper.this.dbHelper.setBoolean(DBHelper.COLUMN_ACCOUNT_CREATED, 1);
			
		}

	}
	
	
	/**
	 * async task to log in the app user. queries the web server and pops up a progress dialog.
	 * @author merrickc
	 *
	 */
	public class loginTask extends AsyncTask<String, Integer, Boolean> {

		
		ProgressDialog dialog;
		
		Context context;
		
		String username;
		
		loginTask(Context context){
			
			this.context = context;
			dialog = new ProgressDialog(context);
			username = null;
		}
		
		@Override
        protected void onPreExecute() {
			super.onPreExecute();
//			dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
//            dialog.setTitle("Logging in...");
//            dialog.setMax(100);
//            dialog.setIndeterminate(true);
//            dialog.show();
			
			try{
				dialog = ProgressDialog.show(WebHelper.this.activity,
		                "", "Logging in...");
			}
			catch(Exception e){
				Log.e("ERROR", e.toString());
			}
			
            
            
        }
		
		@Override
		protected Boolean doInBackground(String... params) {
			
			publishProgress(1);
			
			String username = params[0];
			String password = params[1];
			String rememberMe = params[2];
			
			this.username = username; 
			
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
	        nameValuePairs.add(new BasicNameValuePair("username", username));
	        nameValuePairs.add(new BasicNameValuePair("password",password));
	        nameValuePairs.add(new BasicNameValuePair("rememberMe", rememberMe));
	        
	        
	        
	        HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "/login.php");
		    
		    // Create local HTTP context
		    httpContext = new BasicHttpContext();
		    // Bind custom cookie store to the local context
		    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		    
	        try {
				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

	        // Execute HTTP Post Request
	        try {
				HttpResponse response = httpclient.execute(httppost, httpContext);
				String result = EntityUtils.toString(response.getEntity());
				Log.e("WEB RESPONSE", result);
				JSONObject jsonObject = null;
				try {
					jsonObject = new JSONObject(result);
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				//jsonObject.
				try {
					result = jsonObject.getString("status");
					Log.e(tag, result);
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				if(result.equals("success")) return true;
				
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

	        

	        return false;

		}
		
		@Override
		public void onProgressUpdate(Integer... progress){
			this.dialog.incrementProgressBy(10);
		}
		
		public void onPostExecute(Boolean result){
			
			super.onPostExecute(result);
			
			//dialog.dismiss();
//			if(!result){
//				Toast.makeText(this.context, "Failed to log in", Toast.LENGTH_LONG).show();
//			}

	        if (dialog.isShowing()) {
	            dialog.dismiss();
	        }
	        
	        if(this.context instanceof LoginActivity){
	        	((LoginActivity) this.context).onAuthenticate(this.username, result);
	        }
			
		}


	}
	

	/**
	 * registers the user using async task. 
	 * @author merrickc
	 *
	 */
	public class registerUserTask extends AsyncTask<String, String[], Boolean> {

		ProgressDialog dialog;
		
		Context context;
		
		registerUserTask(Context context){
			
			this.context = context;
			dialog = new ProgressDialog(context);
		}
		
		@Override
        protected void onPreExecute() {
            dialog.setTitle("Registering User...");
            dialog.show();
        }
		
		@Override
		protected Boolean doInBackground(String... params) {
			String username = params[0];
			String password = params[1];
			String email = params[2];

			
			HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "/register.php");
		    
		    
		    // Add your data
	        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
	        nameValuePairs.add(new BasicNameValuePair("username", username));
	        nameValuePairs.add(new BasicNameValuePair("password", password));
	        nameValuePairs.add(new BasicNameValuePair("email", email));
	        try {
				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

	        // Execute HTTP Post Request
	        try {
				HttpResponse response = httpclient.execute(httppost);
				String result = EntityUtils.toString(response.getEntity());
				Log.e("WEB RESPONSE", result);
				
				/** if true, log in user **/
				if(result.equals("success")){
					
					nameValuePairs = new ArrayList<NameValuePair>();
			        nameValuePairs.add(new BasicNameValuePair("username", username));
			        nameValuePairs.add(new BasicNameValuePair("password",password));
			        nameValuePairs.add(new BasicNameValuePair("rememberMe", "0"));
			        
			        
			        
			        httpclient = new DefaultHttpClient();
				    httppost = new HttpPost(DPSSERVER + "/login.php");
				    
				    // Create local HTTP context
				    httpContext = new BasicHttpContext();
				    // Bind custom cookie store to the local context
				    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
				    
			        try {
						httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}

			        // Execute HTTP Post Request
			        try {
						response = httpclient.execute(httppost, httpContext);
						result = EntityUtils.toString(response.getEntity());
						Log.e("WEB RESPONSE", result);
						JSONObject jsonObject = null;
						try {
							jsonObject = new JSONObject(result);
							result = jsonObject.getString("status");
							Log.e(tag, "LOGGING IN AFTER REGISTER");
							Log.e(tag, result);
							
							if(result.equals("success")) {
								
								//WebHelper.this.getAccountInfo();
								WebHelper.this.dbHelper.setUsername(username);
								
								return true;
							}
							
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						
						
						
					} catch (ClientProtocolException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
					
					
					return false;
				}
				
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

			Log.e(tag, "End REgister User");
			return false;
		}
		
		@Override
		protected void onPostExecute(Boolean result){
			
			if(!result){
				Toast.makeText(context, "Could not register user. Check your internet connection", Toast.LENGTH_LONG).show();
			}

			dialog.dismiss();
			
			
		}



	}

	/**
	 * calls async thread to check if username is available. stores result in "onPostExecuteResult"
	 * @author merrickc
	 *
	 */
	public class checkUsernameTask extends AsyncTask<String, Integer, Boolean>{

		ProgressDialog dialog;
		
		Context context;
		
		checkUsernameTask(Context context){
			
			this.context = context;
			dialog = new ProgressDialog(context);
		}
		
		@Override
        protected void onPreExecute() {
            dialog.setTitle("Checking Username...");
            //dialog.show();
        }
		
		@Override
		protected Boolean doInBackground(String... params) {
			
			String username = params[0];
			
			Log.e(tag, "Checking Username Available");
	    	
	    	List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
	        nameValuePairs.add(new BasicNameValuePair("username", username));
	        
			HttpClient httpclient = new DefaultHttpClient();
		    HttpPost httppost = new HttpPost(DPSSERVER + "/checkUserExists.php");
		    
		    // Create local HTTP context
		    HttpContext localContext = new BasicHttpContext();
		    // Bind custom cookie store to the local context
		    localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		    
		    boolean usernameAvailable = false;
		    
		    try {
				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

	        // Execute HTTP Post Request
	        try {
	        	
	        	Log.e(tag, "EXECUTING HTTPPOST");
				HttpResponse response = httpclient.execute(httppost, localContext);
				String result = EntityUtils.toString(response.getEntity());
				Log.e("WEB RESPONSE", result);

				
				/** if server returns 0 accounts with that name **/
				if(Integer.parseInt(result) < 1){
					usernameAvailable = true;
				}
				else{
					usernameAvailable = false;
				}
				
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

	        
	        
	        return usernameAvailable;

		}
		
		@Override
		public void onPostExecute(Boolean result){
			dialog.dismiss();
		}
		
		
	}
	
	
	/**
	 * calls new thread to register user. 
	 * @param username
	 * @param password
	 * @param email
	 * @return true if success. gets result in "onPostExecuteResult" which is set by the thread
	 */
	public Boolean registerUser(String username, String password, String email){
		
		String encryptedPassword = Utility.md5(password);
		
		try {
			if(new registerUserTask(this.activity).execute(username, encryptedPassword, email).get()){
				getAccountInfo();
			}
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		} catch (ExecutionException e) {
			
			e.printStackTrace();
		}
		
		return false;
	}
	
	/**
	 * submit account info to server. 
	 * given content values, containing account data
	 * @return
	 */
	public boolean registerAccount(ContentValues values){
		
		/** extract each of the values and put into POST **/
	    String accountName = values.getAsString(AccountDBHelper.COLUMN_ACCOUNT_NAME);
	    String checkingNum = (String) values.get(AccountDBHelper.COLUMN_ACCOUNT_CHECKNUM);
	    String routeNum = (String) values.get(AccountDBHelper.COLUMN_ACCOUNT_ROUTENUM);
	    
	    String fullName = (String) values.get(AccountDBHelper.COLUMN_ACCOUNT_FULLNAME);
	    String birthdate = (String) values.get(AccountDBHelper.COLUMN_ACCOUNT_BIRTHDATE);
	    String socialSecurity = (String) values.get(AccountDBHelper.COLUMN_ACCOUNT_SOCIAL_SECURITY);
	    String employer = values.getAsString(AccountDBHelper.COLUMN_ACCOUNT_EMPLOYER);
	    
	    String phoneNumber = (String) values.get(AccountDBHelper.COLUMN_ACCOUNT_PHONE_NUMBER);
	    String homeAddress = (String) values.get(AccountDBHelper.COLUMN_ACCOUNT_HOME_ADDRESS);
	    String homeCity = values.getAsString(AccountDBHelper.COLUMN_ACCOUNT_HOME_CITY);
	    String homeState = values.getAsString(AccountDBHelper.COLUMN_ACCOUNT_HOME_CITY);
	    String homeZip = values.getAsString(AccountDBHelper.COLUMN_ACCOUNT_HOME_ZIP);
	    
	    JSONObject object = new JSONObject();
	    
	    try {
	    	object.put("name", accountName);
	    	object.put("checkingNum", checkingNum);
	    	object.put("routeNum", routeNum);
	    	
	    	object.put("fullName", fullName);
	    	object.put("birthdate", birthdate);
	    	object.put("socialSecurity", socialSecurity);
	    	object.put("employer", employer);
	    	
	    	object.put("phoneNumber", phoneNumber);
	    	object.put("homeAddress", homeAddress);
	    	object.put("homeCity", homeCity);
	    	object.put("homeState", homeState);
	    	object.put("homeZip", homeZip);
	    	
	    	//object.put("ownerID", this.dbHelper.getUserID())
	    	
	    	
	    }
	    catch(JSONException e){
	    	e.printStackTrace();
	    }
	    
        
        try {
        	
        	Log.e(tag, "calling create account task");
			if(new createAccountTask().execute(object).get() == true){
				
				this.getAccountInfo();
				this.dbHelper.setBoolean(DBHelper.COLUMN_ACCOUNT_CREATED, 1);
				return true;
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return false;
	}

	/**
	 * calls new thread to check username availability. 
	 * @param username
	 * @return 
	 * @return if success, returns true; grabs result from onPostExecute variable, which is set by the thead in "onPostExecute"
	 */
	public Boolean checkUsernameAvailable(String username) {
		try {
			return new checkUsernameTask(activity).execute(username).get();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		
		return false;
	}
	
	/**
	 * calls new thread to log user in. 
	 * @param username
	 * @param password
	 * @return true/false if success/failed. thread sets result of action to "postExecuteResult" variable;
	 */
	public Boolean login(String username, String password, boolean rememberMe){
		try {
			String rememberUser = "0";
			if(rememberMe) rememberUser = "1";

			if(new loginTask(this.activity).execute(username, Utility.md5(password), rememberUser).get() == true){
				
				this.dbHelper.setUsername(username);
				return true;
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			
			e.printStackTrace();
		}
		
		this.dbHelper.setUsername("");
        return false;
		

	}
	
	public void logout(){
		
		this.cookieStore.clear();
		
		//if remember me, keep username
		if(!this.dbHelper.getBoolean(DBHelper.COLUMN_REMEMBER_ME))
			this.dbHelper.setUsername("");
		
		Toast.makeText(this.activity, "Logged Out", Toast.LENGTH_LONG);
		
		
		
	}

	
	
	/** checks if the user has internet **/
	public boolean hasConnection() {
	    ConnectivityManager cm =
	        (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
	    NetworkInfo netInfo = cm.getActiveNetworkInfo();
	    if (netInfo != null && netInfo.isConnectedOrConnecting()) {
	        return true;
	    }
	    return false;
	}
	
	/**
	 * handles authentication for the user. user must be authenticated to interact with web server and add/view savings
	 */
	@SuppressWarnings("deprecation")
	public boolean authenticate(String returnTab){

		/** check for session cookie **/
		//Cookie cookie;
		cookieStore.clearExpired(new Date());
		
		String username = this.dbHelper.getUsername();
		
		if(username != null){
			
			try {
				if(new checkSessionTask().execute(username).get() == true){
					Log.e(tag, "FOUND COOKIE! and user = " + username + " authenticated");
					return true;
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		
		
		
		
			
		/** no session cookie, request login **/
		Intent intent = new Intent(this.activity, LoginActivity.class);
		
		
		intent.putExtra("START_TAB", returnTab);
		this.activity.startActivity(intent);
		
		return false;
		

	}
	
	/**
	 * determines if the given session token is still active (logged in)
	 * @param token
	 * @return
	 */
	public boolean checkSession(String username){
		
		Log.e(tag, "Checking Session for : " + username);
		
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("username", username));
        
		HttpClient httpclient = new DefaultHttpClient();
	    HttpPost httppost = new HttpPost(DPSSERVER + "/checkSession.php");
	    
	    try {
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	    
	    
	    boolean sessionOpen = false;
	    
	    // Create local HTTP context
	    httpContext = new BasicHttpContext();
	    // Bind custom cookie store to the local context
	    httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
	    


        try {
        	
        	Log.e(tag, "EXECUTING HTTPPOST");
			HttpResponse response = httpclient.execute(httppost, httpContext);
			
			//saveCookies();
			
			String result = EntityUtils.toString(response.getEntity());
			Log.e("WEB RESPONSE", "*** (in check session) result = " +result);

			JSONObject jsonObject = null;
			
			try {
				jsonObject = new JSONObject(result);
				
				result = jsonObject.getString("status");
				
				if(result.equals("success")){
					sessionOpen = true;
					return sessionOpen;
				}
				else{
					sessionOpen = false;
					return sessionOpen;
				}
				
			} catch (JSONException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			

			
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

       return sessionOpen;

	}
	
	/**
	 * get account info for user id
	 * @param userid
	 * @return
	 */
	public void getAccountInfo(){
		
		int userid = this.dbHelper.getUserID();
		
		JSONObject json = null;

		new getAccountInfoTask(this.activity).execute(userid);


	}
	
	
	public void updateAccountInfo(){
		
		this.authenticate("settings");
		
		JSONObject json = new JSONObject();
		
		Cursor accountsCursor = this.accountDBHelper.getAccountsAsCursor();
		Log.e("cursor count webhelper", "count = " + accountsCursor.getCount());
		
		
		for(int i = 0; i < accountsCursor.getCount(); i++){
			
			accountsCursor.moveToPosition(i);
			Log.e("index", "index = " + i);
			
			try{
				json.put("id", accountsCursor.getInt(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_ID)));
				
				json.put("name", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_NAME)));
				json.put("checkNum", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_CHECKNUM)));
				json.put("routeNum", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_ROUTENUM)));
				json.put("amount", accountsCursor.getInt(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_AMOUNT)));
				
				json.put("fullName", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_FULLNAME)));
				
				Log.e("UPDATE ACCOUNT INFO", "FULLNAME == " + accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_FULLNAME)));
				
				json.put("birthdate", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_BIRTHDATE)));
				json.put("socialSecurity", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_SOCIAL_SECURITY)));
				json.put("employer", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_EMPLOYER)));
				json.put("phoneNumber", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_PHONE_NUMBER)));
				
				json.put("homeAddress", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_HOME_ADDRESS)));
				json.put("homeState", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_HOME_STATE)));
				json.put("homeCity", accountsCursor.getString(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_HOME_CITY)));
				json.put("homeZip", accountsCursor.getInt(accountsCursor.getColumnIndex(this.accountDBHelper.COLUMN_ACCOUNT_HOME_ZIP)));
				
				
			}
			catch(JSONException e){
				e.printStackTrace();
			}
			
			
			
			try {
				if(new updateAccountInfoTask(this.activity).execute(json).get() == false){
					//Toast.makeText(this.activity, "Failed to update Account Info", Toast.LENGTH_LONG).show();
				}
				else{
					
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
		}

		
	}
	
	public boolean updateUserInfo(){
		/** TODO update user variables on online server **/
		
		JSONObject json = new JSONObject();
		
		int achConfirmed = 0;
		if(this.dbHelper.getBoolean(DBHelper.COLUMN_ACH_CONFIRMED)) achConfirmed = 1;
		
		
		try {
			json.put("username", this.dbHelper.getUsername());
			json.put("achConfirmed", achConfirmed);
			
			//json.put("password", this.dbHelper.getPassword());
			
			
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			return new updateUserInfoTask().execute(json).get();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return false;
		
	}

	public boolean isLoggedIn() {
		// TODO Auto-generated method stub
		/** check for session cookie **/
		//Cookie cookie;
		cookieStore.clearExpired(new Date());
		
		String username = this.dbHelper.getUsername();
		
		if(cookieStore.getCookies() != null){
			
			for(Cookie cookie : cookieStore.getCookies()){
				
				
				if(cookie.getDomain().equals(DOMAIN) && username != null){
					return true;
				}
			}

			
		}
		
		
		return false;
	}

	/**
	 * adds teh transfer to onlinen DB and performs money switch between accounts
	 * @param from
	 * @param to
	 * @param amount
	 * @return
	 */
	public boolean performTransfer(String from, String to, int amount) {
		// TODO Auto-generated method stub
		
		//connect online to add transfers and check if able
		Account fromAccount = accountDBHelper.getAccountAsAccount(from);
		Account toAccount = accountDBHelper.getAccountAsAccount(to);
		
		int fromID = fromAccount.id;
		int toID = toAccount.id;
		
		
		
		new performTransferTask().execute(fromID, toID, amount);
		
		return this.accountDBHelper.transferMoney(from, to, amount);

	}
	
	public void getTransfers(){
		
		new getTransfersTask().execute();
		
		
	}
	
	

	  
}

